import 'dart:async';

import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:x_project/res/colors.dart';

/// Created by XieXin on 2020/3/30.
/// 登录、注册、获取验证码、密码输入框
class XTextField extends StatefulWidget {
  final TextEditingController controller;
  final double fontSize;
  final int? maxLength;
  final bool autoFocus;
  final TextInputType? keyboardType;
  final String? hintText;
  final FocusNode? focusNode;
  final TextAlign textAlign;
  final List<TextInputFormatter>? inputFormatters;
  final bool isInputPwd;
  final Future<bool> Function()? getVCode;
  final String? rightText;
  final VoidCallback Function()? onRightPressed;
  final bool isShowBorder;
  final TextInputAction? textInputAction;
  final ValueChanged<String>? onSubmitted;
  final double leftPadding;
  final double topPadding;
  final double? rightPadding;
  final double bottomPadding;
  final bool enabled;

  /// 用于集成测试寻找widget
  final String? keyName;

  const XTextField({
    Key? key,
    required this.controller,
    this.fontSize = 16,
    this.maxLength,
    this.autoFocus = false,
    this.keyboardType,
    this.hintText,
    this.focusNode,
    this.textAlign = TextAlign.left,
    this.inputFormatters,
    this.isInputPwd = false,
    this.getVCode,
    this.rightText,
    this.onRightPressed,
    this.isShowBorder = true,
    this.textInputAction,
    this.onSubmitted,
    this.keyName,
    this.leftPadding = 0,
    this.topPadding = 10,
    this.rightPadding,
    this.bottomPadding = 5,
    this.enabled: true,
  }) : super(key: key);

  @override
  XTextFieldState createState() => XTextFieldState();
}

class XTextFieldState extends State<XTextField> {
  bool _isShowPwd = false;
  bool _isShowDelete = false;
  bool _isClick = true;
  double rightPadding = 0;

  ///倒计时秒数
  final int _second = 60;

  ///当前秒数
  late int _currentSecond;
  StreamSubscription? _subscription;

  @override
  void initState() {
    ///获取初始化值
    _isShowDelete = widget.controller.text.isNotEmpty;

    ///监听输入改变
    widget.controller.addListener(() {
      setState(() {
        _isShowDelete = widget.controller.text.isNotEmpty;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    if (widget.rightPadding != null) {
      rightPadding = widget.rightPadding!;
    } else {
      rightPadding = 0;
    }
    if (_isShowDelete) rightPadding += 40.w;
    if (widget.isInputPwd) rightPadding += 42.w;
    if (widget.rightText != null) rightPadding += 120.w;
    if (widget.getVCode != null) rightPadding += 180.w;
    if (_isShowDelete && widget.isInputPwd) {
      rightPadding += 30.w;
    }
    return Stack(
      alignment: Alignment.centerRight,
      children: <Widget>[
        _getTextField(),
        Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Offstage(offstage: !_isShowDelete, child: SizedBox(width: 16.w)),
            _getDeleteButton(),
            Offstage(
                offstage: !widget.isInputPwd, child: SizedBox(width: 16.w)),
            _getEyeButton(),
            Offstage(
                offstage: widget.getVCode == null &&
                    TextUtil.isEmpty(widget.rightText),
                child: SizedBox(width: 16.w)),
            _getCodeButton(),
            _getRightButton(),
          ],
        ),
      ],
    );
  }

  ///获取输入框
  Widget _getTextField() {
    ThemeData themeData = Theme.of(context);
    List<TextInputFormatter>? inputFormatters;
    if (widget.inputFormatters != null) {
      inputFormatters = widget.inputFormatters!;
    } else {
      if (widget.isInputPwd) {
        inputFormatters = [
          FilteringTextInputFormatter.deny(RegExp("[\u4e00-\u9fa5]")),
        ];
      } else {
        if (widget.keyboardType == TextInputType.number ||
            widget.keyboardType == TextInputType.phone) {
          inputFormatters = [FilteringTextInputFormatter.digitsOnly];
        }
      }
    }
    return TextField(
      style: TextStyle(fontSize: widget.fontSize),
      focusNode: widget.focusNode,
      maxLength: widget.maxLength,
      obscureText: widget.isInputPwd ? !_isShowPwd : false,
      autofocus: widget.autoFocus,
      controller: widget.controller,
      textAlign: widget.textAlign,
      textInputAction: widget.textInputAction,
      enabled: widget.enabled,
      onSubmitted: widget.onSubmitted,
      keyboardType: widget.keyboardType,
      textAlignVertical: TextAlignVertical.center,
      // 数字、手机号限制格式为0到9(白名单)， 密码限制不包含汉字（黑名单）
      inputFormatters: inputFormatters,
      decoration: InputDecoration(
        isDense: true,
        contentPadding: EdgeInsets.only(
          left: widget.leftPadding,
          right: rightPadding,
          top: widget.topPadding,
          bottom: widget.bottomPadding,
        ),
        hintText: widget.hintText,
        hintStyle: TextStyle(fontSize: widget.fontSize),
        counterText: "",
        border: !widget.isShowBorder ? InputBorder.none : null,
        focusedBorder: UnderlineInputBorder(
          borderSide: BorderSide(
            color: !widget.isShowBorder
                ? Colors.transparent
                : themeData.primaryColor,
            width: 1,
          ),
        ),
        enabledBorder: UnderlineInputBorder(
          borderSide: BorderSide(
            color: !widget.isShowBorder
                ? Colors.transparent
                : Get.theme.dividerColor,
            width: 1,
          ),
        ),
      ),
    );
  }

  ///获取删除按钮
  Widget _getDeleteButton() {
    return _isShowDelete
        ? Semantics(
            label: "清空",
            hint: "清空输入框",
            child: InkWell(
              child: Padding(
                padding: EdgeInsets.symmetric(vertical: widget.bottomPadding),
                child: Icon(
                  const IconData(0xe781, fontFamily: "Icons"),
                  size: 30.w,
                  color: XColors.textColorB1,
                ),
              ),
              onTap: () => widget.controller.text = "",
            ),
          )
        : const SizedBox.shrink();
  }

  ///获取眼睛按钮
  Widget _getEyeButton() {
    return widget.isInputPwd
        ? Semantics(
            label: "密码可见开关",
            hint: "密码是否可见",
            child: InkWell(
              onTap: () {
                setState(() {
                  _isShowPwd = !_isShowPwd;
                });
              },
              child: Padding(
                padding: EdgeInsets.symmetric(vertical: widget.bottomPadding),
                child: Icon(
                  IconData(_isShowPwd ? 0xe7a4 : 0xe9aa, fontFamily: "Icons"),
                  size: 32.w,
                  color: XColors.textColorB1,
                ),
              ),
            ),
          )
        : const SizedBox.shrink();
  }

  ///获取右边按钮
  Widget _getRightButton() {
    if (TextUtil.isEmpty(widget.rightText) || widget.getVCode != null) {
      return const SizedBox.shrink();
    }
    return InkWell(
      onTap: widget.onRightPressed,
      child: Padding(
        padding: EdgeInsets.symmetric(vertical: widget.bottomPadding),
        child: Text(
          widget.rightText!,
          style: TextStyle(fontSize: ScreenUtil().setSp(28.0)),
        ),
      ),
    );
  }

  ///获取验证码按钮
  Widget _getCodeButton() {
    if (widget.getVCode == null) return const SizedBox.shrink();
    return InkWell(
      onTap: _isClick ? _getCode : null,
      child: Padding(
        padding: EdgeInsets.symmetric(vertical: widget.bottomPadding),
        child: Text(
          _isClick ? "获取验证码" : "${_currentSecond}S",
          style: TextStyle(fontSize: ScreenUtil().setSp(28.0)),
        ),
      ),
    );
  }

  Future _getCode() async {
    bool isSuccess = await widget.getVCode!();
    if (isSuccess) {
      setState(() {
        _currentSecond = _second;
        _isClick = false;
      });
      _subscription = Stream.periodic(const Duration(seconds: 1), (i) => i)
          .take(_second + 1)
          .listen((i) {
        setState(() {
          _currentSecond = _second - i - 1;
          _isClick = _currentSecond < 1;
        });
      });
    }
  }

  @override
  void dispose() {
    widget.controller.removeListener(() {});
    _subscription?.cancel();
    super.dispose();
  }
}
